﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.ServiceModel;

namespace Project.Web.Base
{
	public class ServiceFactory
	{
		private static Dictionary<Type, object> objBizDictionary = new Dictionary<Type, object>();
		private static Dictionary<Type, ChannelFactory> objBizChannelFactoryDictionary = new Dictionary<Type, ChannelFactory>();
		private static object asyn = new object();
		public static object Get(Type t)
		{
			Object o = null;
			MethodInfo createchannel = null;
			lock (asyn)
			{
				foreach (Type i in objBizDictionary.Keys)
				{
					if (i == t)
					{
						o = objBizDictionary[i];
						return o;
					}
				}
				WSHttpBinding binding = new WSHttpBinding("wsHttpBinding-binding");
				Type channelFactoryType = typeof(ChannelFactory<>);
				channelFactoryType = channelFactoryType.MakeGenericType(t);
				ChannelFactory channelFactory = (ChannelFactory)Activator.CreateInstance(channelFactoryType, binding, new EndpointAddress("http://localhost:9988/" + t.Name.Substring(1)) + ".svc/wsHttp");
				channelFactory.Credentials.UserName.UserName = "zhanghucheng";
				channelFactory.Credentials.UserName.Password = "password";
				channelFactory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
				channelFactory.Open();


				createchannel = channelFactory.GetType().GetMethod("CreateChannel", new Type[0]);
				o = createchannel.Invoke(channelFactory, null);
				((ICommunicationObject)o).Faulted += new EventHandler(ICommunicationObject_Faulted);

				//获得注入方法，并进行注入
				MethodInfo injectMethod = t.GetMethod("Inject");
				if (injectMethod != null)
					injectMethod.Invoke(o, null);
				objBizDictionary.Add(t, o);
				objBizChannelFactoryDictionary.Add(t, channelFactory);
				return o;
			}
		}

		static void ICommunicationObject_Faulted(object sender, EventArgs e)
		{
			foreach (var item in objBizDictionary.Keys)
			{
				if (objBizDictionary[item].Equals(sender))
				{
					ChannelFactory tempChannelFactory = objBizChannelFactoryDictionary[item];
					if (tempChannelFactory.State == CommunicationState.Closed
						|| tempChannelFactory.State == CommunicationState.Closing
						|| tempChannelFactory.State == CommunicationState.Faulted)
					{
						tempChannelFactory.Open();
					}

					MethodInfo createchannel = tempChannelFactory.GetType().GetMethod("CreateChannel", new Type[0]);
					var o = createchannel.Invoke(tempChannelFactory, null);
					objBizDictionary[item] = o;
					((ICommunicationObject)o).Faulted += new EventHandler(ICommunicationObject_Faulted);

					break;
				}
			}
		}


		public static T Get<T>()
		{
			object o = Get(typeof(T));
			return (T)o;
		}

	}
}
